package com.toolmanrln.logistics.modules.user.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.toolmanrln.common.api.dto.TokenDTO;
import com.toolmanrln.logistics.modules.user.entity.User;
import com.toolmanrln.logistics.modules.user.mapper.UserMapper;
import com.toolmanrln.logistics.modules.user.service.IUserService;
import com.toolmanrln.security.component.VerifyCodeAuthenticationProvider;
import com.toolmanrln.security.util.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author ToolMan.RLN
 * @since 2020-05-19
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    public User register(String account, String password, HttpServletRequest request) {
        VerifyCodeAuthenticationProvider.checkVerifyCode(request);
        Assert.notBlank(account, "账号不能为空");
        Assert.notBlank(password, "账号不能为空");
        Assert.state(password.trim().length() > 5 && password.trim().length() < 17, "密码长度必须为6到16位");
        //查询是否有相同用户名的用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(User::getAccount, account);
        Assert.state(count(queryWrapper) == 0, "账号已存在，请另起一个账号名。");
        User user = new User();
        user.setAccount(account);
        //将密码进行加密操作
        String encodePassword = passwordEncoder.encode(password);
        user.setPassword(encodePassword);
        if (save(user)) {
            return user;
        }
        return null;
    }

    @Override
    public User getByAccount(String account) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(User::getAccount, account);
        return getOne(queryWrapper);
    }

    @Override
    public TokenDTO login(String account, String password, HttpServletRequest request) {
        String token = null;
        //密码需要客户端加密后传递
        try {
            UserDetails userDetails = userDetailsService.loadUserByUsername(account);
            if (!passwordEncoder.matches(password, userDetails.getPassword())) {
                throw new BadCredentialsException("密码不正确");
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(userDetails);
        } catch (AuthenticationException e) {
            log.warn("登录异常:{}", e.getMessage());
        }
        return new TokenDTO(token, null);
    }
}
